www.gusucode.com > C++ 实现可控的3D旋转立方体-源码程序 > C++ 实现可控的3D旋转立方体-源码程序/code/Scene.cpp
// Scene.cpp: implementation of the CScene class. // Download by http://www.NewXing.com ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include <math.h> #include "2DCube.h" #include "Scene.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CScene::CScene() {} CScene::~CScene() {} int CScene::SetMatrix(int matkind,Matrix * mat) { if( NULL == mat ) return 0; switch (matkind) { case MAT_WORLD: memcpy( (void *)&m_WorldMatrix , (void *)mat , sizeof(Matrix) ); break; case MAT_VIEW: memcpy( (void *)&m_ViewMatrix , (void *)mat , sizeof(Matrix) ); break; case MAT_PROJ: memcpy( (void *)&m_ProjMatrix , (void *)mat , sizeof(Matrix) ); break; default: break; } return 1; } //SetProjection用于把一个矩阵设置为透视投影矩阵。 Matrix * CScene::SetProjection(Matrix * projmat,float nearclip, float farclip, float fov) { IdentifyMatrix(projmat); projmat ->_a43 = 1/nearclip; projmat ->_a44 = 0; return projmat; } //SetViewLookAt函数用于把一个矩阵设置为视矩阵。其实现如下: Matrix * CScene::SetViewLookAt(Matrix * matView,Vert3 *vlookat, Vert3 *vEye, Vert3 *updir) { Vert3 u,v,n; Matrix matvrp; float mo; n.x = vlookat->x - vEye->x; //计算向量n n.y = vlookat->y - vEye->y; n.z = vlookat->z - vEye->z; ChaMult(&u,updir,&n); //updir叉乘n得到u ChaMult(&v,&n,&u); //n叉乘u得到v mo = ::sqrtf(u.x * u.x + u.y * u.y + u.z * u.z);//计算向量模长 u.x /= mo; //化为单位向量 u.y /= mo; u.z /= mo; mo = ::sqrtf(v.x * v.x + v.y * v.y + v.z * v.z); v.x /= mo; v.y /= mo; v.z /= mo; mo = ::sqrtf(n.x * n.x + n.y * n.y + n.z * n.z); n.x /= mo; n.y /= mo; n.z /= mo; IdentifyMatrix(matView); //设置复合的旋转矩阵 matView->_a11 = u.x; matView->_a12 = u.y; matView->_a13 = u.z; matView->_a21 = v.x; matView->_a22 = v.y; matView->_a23 = v.z; matView->_a31 = n.x; matView->_a32 = n.y; matView->_a33 = n.z; IdentifyMatrix(&matvrp); //设置平移矩阵 matvrp._a14 = -vEye->x; matvrp._a24 = -vEye->y; matvrp._a34 = -vEye->z; MultMatrix(matView,matView,&matvrp); //两矩阵相乘,得到最终的变换矩阵 return matView; } //矩阵右乘表示摄像机位置的矩阵matvrp实现摄像机的平移,得到最终的视矩阵。 //函数IdentifyMatrix把一个矩阵单位化: Matrix * CScene::IdentifyMatrix(Matrix * mat) { mat->_a11 = 1.0f; mat->_a12 = 0.0f; mat->_a13 = 0.0f; mat->_a14 = 0.0f; mat->_a21 = 0.0f; mat->_a22 = 1.0f; mat->_a23 = 0.0f; mat->_a24 = 0.0f; mat->_a31 = 0.0f; mat->_a32 = 0.0f; mat->_a33 = 1.0f; mat->_a34 = 0.0f; mat->_a41 = 0.0f; mat->_a42 = 0.0f; mat->_a43 = 0.0f; mat->_a44 = 1.0f; return mat; } //函数MatRotation把一个矩阵设置为旋转变换矩阵。其实现如下: Matrix * CScene::MatRotation(Matrix * mat,float alpha,int axis) { float sinalpha = (float)sin(alpha); float cosalpha = (float)cos(alpha); switch (axis) //依照参数值设置关于不同轴的旋转矩阵 { case AXIS_X: { mat->_a11 = 1.0f; mat->_a12 = 0.0f; mat->_a13 = 0.0f; mat->_a14 = 0.0f; mat->_a21 = 0.0f; mat->_a22 = cosalpha; mat->_a23 = -sinalpha; mat->_a24 =0.0f ; mat->_a31 = 0.0f; mat->_a32 = sinalpha; mat->_a33 = cosalpha; mat->_a34 = 0.0f; mat->_a41 = 0.0f; mat->_a42 = 0.0f; mat->_a43 = 0.0f; mat->_a44 = 1.0f; } break; case AXIS_Y: { mat ->_a11 = cosalpha; mat ->_a12 = 0.0f; mat ->_a13 = sinalpha; mat ->_a14 = 0.0f; mat ->_a21 = 0.0f; mat ->_a22 = 1.0f; mat ->_a23 = 0.0f; mat ->_a24 = 0.0f; mat ->_a31 = -sinalpha; mat ->_a32 = 0.0f; mat ->_a33 = cosalpha; mat ->_a34 = 0.0f; mat ->_a41 = 0.0f; mat ->_a42 = 0.0f; mat ->_a43 = 0.0f; mat ->_a44 = 1.0f; } break; case AXIS_Z: { mat ->_a11 = cosalpha; mat ->_a12 = -sinalpha; mat ->_a13 = 0.0f; mat ->_a14 = 0.0f; mat ->_a21 = sinalpha; mat ->_a22 = cosalpha; mat ->_a23 = 0.0f; mat ->_a24 = 0.0f; mat ->_a31 = 0.0f; mat ->_a32 = 0.0f; mat ->_a33 = 1.0f; mat ->_a34 = 0.0f; mat ->_a41 = 0.0f; mat ->_a42 = 0.0f; mat ->_a43 = 0.0f; mat ->_a44 = 1.0f; } break; default: break; } return mat; } //函数MatTranslation与MatRotation类似,它完成把一个矩阵设为平移变换矩阵的工作。其实现如下: //函数的第一个参数是要被设置的矩阵,第二个参数是旋转的角度,第三个参数是旋转轴,必须为上面三个宏中的一个。该函数针对不同轴的旋转,把矩阵设为三种旋转矩阵中的一种。 Matrix * CScene::MatTranslation(Matrix * mat,float xoffset,float yoffset,float zoffset) { mat ->_a11 = 1.0f; mat ->_a12 = 0.0f; mat ->_a13 = 0.0f; mat ->_a14 = xoffset; mat ->_a21 = 0.0f; mat ->_a22 = 1.0f; mat ->_a23 = 0.0f; mat ->_a24 = yoffset; mat ->_a31 = 0.0f; mat ->_a32 = 0.0f; mat ->_a33 = 1.0f; mat ->_a34 = zoffset; mat ->_a41 = 0.0f; mat ->_a42 = 0.0f; mat ->_a43 = 0.0f; mat ->_a44 = 1.0f; return mat; } //函数MultMatrix实现矩阵乘法: Matrix * CScene::MultMatrix(Matrix * outmat,Matrix * inmat1,Matrix * inmat2) { Matrix matout; matout._a11 = (inmat1 ->_a11) * (inmat2 ->_a11) + (inmat1 ->_a12) * (inmat2 ->_a21) + (inmat1 ->_a13) * (inmat2 ->_a31) + (inmat1 ->_a14) * (inmat2 ->_a41) ; matout._a12 = (inmat1 ->_a11) * (inmat2 ->_a12) + (inmat1 ->_a12) * (inmat2 ->_a22) + (inmat1 ->_a13) * (inmat2 ->_a32) + (inmat1 ->_a14) * (inmat2 ->_a42) ; matout._a13 = (inmat1 ->_a11) * (inmat2 ->_a13) + (inmat1 ->_a12) * (inmat2 ->_a23) + (inmat1 ->_a13) * (inmat2 ->_a33) + (inmat1 ->_a14) * (inmat2 ->_a43) ; matout._a14 = (inmat1 ->_a11) * (inmat2 ->_a14) + (inmat1 ->_a12) * (inmat2 ->_a24) + (inmat1 ->_a13) * (inmat2 ->_a34) + (inmat1 ->_a14) * (inmat2 ->_a44) ; matout._a21 = (inmat1 ->_a21) * (inmat2 ->_a11) + (inmat1 ->_a22) * (inmat2 ->_a21) + (inmat1 ->_a23) * (inmat2 ->_a31) + (inmat1 ->_a24) * (inmat2 ->_a41) ; matout._a22 = (inmat1 ->_a21) * (inmat2 ->_a12) + (inmat1 ->_a22) * (inmat2 ->_a22) + (inmat1 ->_a23) * (inmat2 ->_a32) + (inmat1 ->_a24) * (inmat2 ->_a42) ; matout._a23 = (inmat1 ->_a21) * (inmat2 ->_a13) + (inmat1 ->_a22) * (inmat2 ->_a23) + (inmat1 ->_a23) * (inmat2 ->_a33) + (inmat1 ->_a24) * (inmat2 ->_a43) ; matout._a24 = (inmat1 ->_a21) * (inmat2 ->_a14) + (inmat1 ->_a22) * (inmat2 ->_a24) + (inmat1 ->_a23) * (inmat2 ->_a34) + (inmat1 ->_a24) * (inmat2 ->_a44) ; matout._a31 = (inmat1 ->_a31) * (inmat2 ->_a11) + (inmat1 ->_a32) * (inmat2 ->_a21) + (inmat1 ->_a33) * (inmat2 ->_a31) + (inmat1 ->_a34) * (inmat2 ->_a41) ; matout._a32 = (inmat1 ->_a31) * (inmat2 ->_a12) + (inmat1 ->_a32) * (inmat2 ->_a22) + (inmat1 ->_a33) * (inmat2 ->_a32) + (inmat1 ->_a34) * (inmat2 ->_a42) ; matout._a33 = (inmat1 ->_a31) * (inmat2 ->_a13) + (inmat1 ->_a32) * (inmat2 ->_a23) + (inmat1 ->_a33) * (inmat2 ->_a33) + (inmat1 ->_a34) * (inmat2 ->_a43) ; matout._a34 = (inmat1 ->_a31) * (inmat2 ->_a14) + (inmat1 ->_a32) * (inmat2 ->_a24) + (inmat1 ->_a33) * (inmat2 ->_a34) + (inmat1 ->_a34) * (inmat2 ->_a44) ; matout._a41 = (inmat1 ->_a41) * (inmat2 ->_a11) + (inmat1 ->_a42) * (inmat2 ->_a21) + (inmat1 ->_a43) * (inmat2 ->_a31) + (inmat1 ->_a44) * (inmat2 ->_a41) ; matout._a42 = (inmat1 ->_a41) * (inmat2 ->_a12) + (inmat1 ->_a42) * (inmat2 ->_a22) + (inmat1 ->_a43) * (inmat2 ->_a32) + (inmat1 ->_a44) * (inmat2 ->_a42) ; matout._a43 = (inmat1 ->_a41) * (inmat2 ->_a13) + (inmat1 ->_a42) * (inmat2 ->_a23) + (inmat1 ->_a43) * (inmat2 ->_a33) + (inmat1 ->_a44) * (inmat2 ->_a43) ; matout._a44 = (inmat1 ->_a41) * (inmat2 ->_a14) + (inmat1 ->_a42) * (inmat2 ->_a24) + (inmat1 ->_a43) * (inmat2 ->_a34) + (inmat1 ->_a44) * (inmat2 ->_a44) ; memcpy( (void *)outmat , (void *)&matout , sizeof(Matrix) ); return outmat; } //DrawPrimtive函数。它的作用是依照设置的三种矩阵的变换,在显示器上绘制vertexbuf中所有点表示的多边形图元。其实现如下: void CScene::DrawPrimtive(HDC hdc,int nVertex,Vert3 * vertexbuf) { Matrix matcombined; //用于纪录矩阵运算结果 IdentifyMatrix(&matcombined); //依次与三个矩阵相乘 MultMatrix( &matcombined , &matcombined , &m_ProjMatrix ); MultMatrix( &matcombined , &matcombined , &m_ViewMatrix ); MultMatrix( &matcombined , &matcombined , &m_WorldMatrix ); Vert3 destcur ; Vert3 destlast; Vert3 * sourcecur = vertexbuf; SetPixel( hdc , 0 , 0 , RGB(0,0,0) ); MultVertWithMatrix( &destlast , sourcecur , &matcombined ); //将向量与结果矩阵相乘,得到//变换后的向量 sourcecur ++; //循环绘制多边形图元所有的边 for (int j = 1 ; j < nVertex ; j++ ) { MoveToEx( hdc , 100 + (int)destlast.x / destlast.w , 100 + (int)destlast.y / destlast.w , NULL ); MultVertWithMatrix( &destcur , sourcecur , &matcombined ); LineTo( hdc , 100 + (int)destcur.x / destcur.w , 100 + (int)destcur.y / destcur.w ); memcpy( (void * )&destlast , (void * )&destcur , sizeof(Vert3) ); sourcecur ++; }//绘制到最后一个顶点; //把最后一个顶点与第一个相连; MoveToEx( hdc , 100 + (int)destlast.x / destlast.w , 100 + (int)destlast.y / destlast.w , NULL ); MultVertWithMatrix( &destcur , vertexbuf , &matcombined ); LineTo( hdc , 100 + (int)destcur.x / destcur.w , 100 + (int)destcur.y/destcur.w ); } //DianMult:实现向量的点乘 float CScene::DianMult(Vert3 *vertin1, Vert3 *vertin2) { return ( (vertin1 ->x) * (vertin2 ->x) + (vertin1 ->y) * (vertin2 ->y) + (vertin1 ->z) * (vertin2 ->z) ) ; } //ChaMult:实现向量的叉乘 Vert3 * CScene::ChaMult(Vert3 *vertout, Vert3 *vertu, Vert3 *vertv) { Vert3 out; out.x = (vertu ->y) * (vertv ->z) - (vertv ->y) * (vertu ->z) ; out.y = (vertv ->x) * (vertu ->z) - (vertu ->x) * (vertv ->z) ; out.z = (vertu ->x) * (vertv ->y) - (vertv ->x) * (vertu ->y) ; memcpy( vertout , &out , sizeof(Vert3) ); return vertout; } //MultVertWithMatrix:实现向量与矩阵的乘法 void CScene::MultVertWithMatrix(Vert3 *vertout, Vert3 *vertin, Matrix *mat) { vertout ->x = (mat ->_a11) * (vertin ->x) + (mat ->_a12) * (vertin ->y) + (mat ->_a13) * (vertin ->z) + (mat ->_a14) * (vertin ->w) ; vertout ->y = (mat ->_a21) * (vertin ->x) + (mat ->_a22) * (vertin ->y) + (mat ->_a23) * (vertin ->z) + (mat ->_a24) * (vertin ->w) ; vertout ->z = (mat ->_a31) * (vertin ->x) + (mat ->_a32) * (vertin ->y) + (mat ->_a33) * (vertin ->z) + (mat ->_a34) * (vertin ->w) ; vertout ->w = (mat ->_a41) * (vertin ->x) + (mat ->_a42) * (vertin ->y) + (mat ->_a43) * (vertin ->z) + (mat ->_a44) * (vertin ->w) ; }